/*
 * Copyright (c) 2022, IMMORTA Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * - Neither the name of IMMORTA Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef UART_LIN_REG_ACCESS_H
#define UART_LIN_REG_ACCESS_H

/*!
 * @file uart_lin_reg_access.h
 * @brief This file declares or defines uart register access functions
 */

/*******Includes***************************************************************/
#include "device_registers.h"

/*******Definitions************************************************************/
#define UART_LCR_LBKLTX(x)   (((uint32_t)(((uint32_t)(x)) << UART_LCR_LBKLTX_Pos)) & UART_LCR_LBKLTX_Msk)
#define UART_LCR_LBKLCK(x)   (((uint32_t)(((uint32_t)(x)) << UART_LCR_LBKLCK_Pos)) & UART_LCR_LBKLCK_Msk)
#define UART_LCR_LEN(x)      (((uint32_t)(((uint32_t)(x)) << UART_LCR_LEN_Pos)) & UART_LCR_LEN_Msk)
#define UART_LCR_LABREN(x)   (((uint32_t)(((uint32_t)(x)) << UART_LCR_LABREN_Pos)) & UART_LCR_LABREN_Msk)
#define UART_LCR_LSYCEIEN(x) (((uint32_t)(((uint32_t)(x)) << UART_LCR_LSYCEIEN_Pos)) & UART_LCR_LSYCEIEN_Msk)
#define UART_LCR_LBKIEN(x)   (((uint32_t)(((uint32_t)(x)) << UART_LCR_LBKIEN_Pos)) & UART_LCR_LBKIEN_Msk)
#define UART_LCR_LBUSEIEN(x) (((uint32_t)(((uint32_t)(x)) << UART_LCR_LBUSEIEN_Pos)) & UART_LCR_LBUSEIEN_Msk)
#define UART_LCR_LTBK(x)     (((uint32_t)(((uint32_t)(x)) << UART_LCR_LTBK_Pos)) & UART_LCR_LTBK_Msk)

/*!
 * @brief LIN break character length settings for transmit
 */
typedef enum {
    LIN_BREAK_CHAR_TRANSMIT_13_BIT = 0x00U,  /*!< LIN break char length 13 bit times */
    LIN_BREAK_CHAR_TRANSMIT_14_BIT = 0x01U,  /*!< LIN break char length 14 bit times */
    LIN_BREAK_CHAR_TRANSMIT_15_BIT = 0x02U,  /*!< LIN break char length 15 bit times */
    LIN_BREAK_CHAR_TRANSMIT_16_BIT = 0x03U,  /*!< LIN break char length 16 bit times */
    LIN_BREAK_CHAR_TRANSMIT_17_BIT = 0x04U,  /*!< LIN break char length 17 bit times */
    LIN_BREAK_CHAR_TRANSMIT_18_BIT = 0x05U,  /*!< LIN break char length 18 bit times */
    LIN_BREAK_CHAR_TRANSMIT_19_BIT = 0x06U,  /*!< LIN break char length 19 bit times */
    LIN_BREAK_CHAR_TRANSMIT_20_BIT = 0x07U,  /*!< LIN break char length 20 bit times */
    LIN_BREAK_CHAR_TRANSMIT_21_BIT = 0x08U,  /*!< LIN break char length 21 bit times */
    LIN_BREAK_CHAR_TRANSMIT_22_BIT = 0x09U,  /*!< LIN break char length 22 bit times */
    LIN_BREAK_CHAR_TRANSMIT_23_BIT = 0x0AU,  /*!< LIN break char length 23 bit times */
    LIN_BREAK_CHAR_TRANSMIT_24_BIT = 0x0BU,  /*!< LIN break char length 24 bit times */
    LIN_BREAK_CHAR_TRANSMIT_25_BIT = 0x0CU,  /*!< LIN break char length 25 bit times */
    LIN_BREAK_CHAR_TRANSMIT_26_BIT = 0x0DU,  /*!< LIN break char length 26 bit times */
    LIN_BREAK_CHAR_TRANSMIT_27_BIT = 0x0EU,  /*!< LIN break char length 27 bit times */
    LIN_BREAK_CHAR_TRANSMIT_28_BIT = 0x0FU   /*!< LIN break char length 28 bit times */
} lin_break_char_transmit_length_t;

/*!
 * @brief LIN break character length settings for detect
 */
typedef enum {
    LIN_BREAK_CHAR_DETECT_11_BIT = 0U,  /*!< LIN break char length 11 bit times */
    LIN_BREAK_CHAR_DETECT_10_BIT = 1U   /*!< LIN break char length 10 bit times */
} lin_break_char_detect_length_t;

/*******APIs*******************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif

/*!
 * @brief  UART break character transmit length configuration
 *
 * This function configures the break char length.
 * In some UART instances, the user should disable the transmitter before calling this function.
 * Generally, this may be applied to all UARTs to ensure safe operation
 *
 * @param[in] regBase:   UART register base pointer
 * @param[in] length: LIN break character length setting:
 *      LIN_BREAK_CHAR_TRANSMIT_13_BIT = 0x00U,  LIN break char length 13 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_14_BIT = 0x01U,  LIN break char length 14 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_15_BIT = 0x02U,  LIN break char length 15 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_16_BIT = 0x03U,  LIN break char length 16 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_17_BIT = 0x04U,  LIN break char length 17 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_18_BIT = 0x05U,  LIN break char length 18 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_19_BIT = 0x06U,  LIN break char length 19 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_20_BIT = 0x07U,  LIN break char length 20 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_21_BIT = 0x08U,  LIN break char length 21 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_22_BIT = 0x09U,  LIN break char length 22 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_23_BIT = 0x0AU,  LIN break char length 23 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_24_BIT = 0x0BU,  LIN break char length 24 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_25_BIT = 0x0CU,  LIN break char length 25 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_26_BIT = 0x0DU,  LIN break char length 26 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_27_BIT = 0x0EU,  LIN break char length 27 bit times
 *      LIN_BREAK_CHAR_TRANSMIT_28_BIT = 0x0FU   LIN break char length 28 bit times
 * @return None
 */
static inline void UART_LIN_REG_SetTransmitBreakCharLength(UART_Type* regBase,
                                                           lin_break_char_transmit_length_t length)
{
    regBase->LCR = ((regBase->LCR & ~UART_LCR_LBKLTX_Msk) | UART_LCR_LBKLTX(length));
}

/*!
 * @brief  UART break character detect length configuration
 *
 * @param[in] regBase:    UART register base pointer
 * @param[in] length:  LIN break character length setting:
 *      LIN_BREAK_CHAR_DETECT_10_BIT = 0x01U,  LIN break char length 10 bit times
 *      LIN_BREAK_CHAR_DETECT_11_BIT = 0x00U   LIN break char length 11 bit times
 * @return None
 */
static inline void UART_LIN_REG_SetBreakCharDetectLength(UART_Type* regBase,
                                                         lin_break_char_detect_length_t length)
{
    regBase->LCR = ((regBase->LCR & ~UART_LCR_LBKLCK_Msk) | UART_LCR_LBKLCK(length));
}

/*!
 * @brief  UART transmit break character configuration
 *
 * @param[in] regBase: UART register base pointer
 * @return None
 */

static inline void UART_LIN_REG_TransmitBreakField(UART_Type* regBase)
{
    /* Write 1 to LTBK Trigger a break */
    regBase->LCR = ((regBase->LCR & ~UART_LCR_LTBK_Msk) | UART_LCR_LTBK(1U));
}

/*!
 * @brief Enable or disable the UART lin function
 *
 * @param[in] regBase:   UART register base pointer
 * @param[in] enable: true - enable, false - disable
 * @return None
 */
static inline void UART_LIN_REG_SetLinEnable(UART_Type* regBase,
                                             bool enable)
{
    regBase->LCR = ((regBase->LCR & ~UART_LCR_LEN_Msk) | UART_LCR_LEN(enable ? 1U : 0U));
}

/*!
 * @brief Enable or disable the UART lin autobaud rate
 *
 * @param[in] regBase:   UART register base pointer
 * @param[in] enable: true - enable, false - disable
 * @return None
 */
static inline void UART_LIN_REG_SetAutoBaudEnable(UART_Type* regBase,
                                                  bool enable)
{
    regBase->LCR = ((regBase->LCR & ~UART_LCR_LABREN_Msk) | UART_LCR_LABREN(enable ? 1U : 0U));
}

/*!
 * @brief Set the uart lin sync error interrupt enable
 *
 * @param[in] regBase:   Uart register base address
 * @param[in] enable: Enable flag
 *            - true: Enable sync error interrupt
 *            - false: Disable sync error interrupt
 * @return None
 */
static inline void UART_LIN_REG_SetSyncErrorIntEnable(UART_Type* regBase,
                                                      bool enable)
{
    regBase->LCR = ((regBase->LCR & ~UART_LCR_LSYCEIEN_Msk) | UART_LCR_LSYCEIEN(enable ? 1U : 0U));
}

/*!
 * @brief Set the uart lin break detect interrupt enable
 *
 * @param[in] regBase:   Uart register base address
 * @param[in] enable: Enable flag
 *            - true: Enable break detect interrupt
 *            - false: Disable break detect interrupt
 * @return None
 */
static inline void UART_LIN_REG_SetBreakDetectIntEnable(UART_Type* regBase,
                                                        bool enable)
{
    regBase->LCR = ((regBase->LCR & ~UART_LCR_LBKIEN_Msk) | UART_LCR_LBKIEN(enable ? 1U : 0U));
}

/*!
 * @brief Set the uart lin bus error interrupt enable
 *
 * @param[in] regBase:   Uart register base address
 * @param[in] enable: Enable flag
 *            - true: Enable lin bus error interrupt
 *            - false: Disable lin bus error interrupt
 * @return None
 */
static inline void UART_LIN_REG_SetBusErrorIntEnable(UART_Type* regBase,
                                                     bool enable)
{
    regBase->LCR = ((regBase->LCR & ~UART_LCR_LBUSEIEN_Msk) | UART_LCR_LBUSEIEN(enable ? 1U : 0U));
}

#if defined(__cplusplus)
}
#endif

#endif /* UART_LIN_REG_ACCESS_H */

/*******EOF********************************************************************/
